﻿#ifdef _WIN32
#include "windows_defines.h"
#endif

#include "../../../../../../unittest/framework/unittest.hh"

#include "guildservicewelfare.enum.h"
#include "guildservicewelfare/GuildRedEnvelopeBrief_struct.h"

#include "CreateGuildArg_struct.h"
#include "CreateGuildRes_struct.h"
#include "ApplyJoinGuildArg_struct.h"
#include "ApplyJoinGuildRes_struct.h"
#include "SetAutoApprovalArg_struct.h"
#include "SetAutoApprovalRes_struct.h"
#include "SendGuildRedEnvelopeArg_struct.h"
#include "SendGuildRedEnvelopeRes_struct.h"
#include "GuildRedEnvelopeGrabber_struct.h"
#include "GrabGuildRedEnvelopeArg_struct.h"
#include "GrabGuildRedEnvelopeRes_struct.h"
#include "guildservicewelfare/LoginArg_struct.h"
#include "guildservicewelfare/LoginRes_struct.h"
#include "guildservicewelfare/LogoutNtfData_struct.h"
#include "SetGuildAuctionOfferArg_struct.h"
#include "SetGuildAuctionOfferRes_struct.h"
#include "SetGuildAuctionAttentionArg_struct.h"
#include "SetGuildAuctionAttentionRes_struct.h"
#include "RegisterArg_struct.h"
#include "RegisterRes_struct.h"
#include "UnregisterNtfData_struct.h"
#include "AddGuildRepositoryCellItemArg_struct.h"
#include "AddGuildRepositoryCellItemRes_struct.h"
#include "DelGuildRepositoryCellItemArg_struct.h"
#include "DelGuildRepositoryCellItemRes_struct.h"

#include "GuildRepositoryCellRoleView_struct.h"
#include "GuildRepositoryAuctionRoleView_struct.h"
#include "GuildRepositoryAuctionItemRoleView_struct.h"
#include "GetGuildRepositoryRoleViewArg_struct.h"
#include "GetGuildRepositoryRoleViewRes_struct.h"
#include "GetGuildWelfareAwardArg_struct.h"
#include "GetGuildWelfareAwardRes_struct.h"
#include "QueryGuildWelfareAwardArg_struct.h"
#include "QueryGuildWelfareAwardRes_struct.h"

#include "box/service_box.hh"
#include "box/service_context.hh"
#include "detail/service_context_impl.hh"

#include "guild_service_basic_context.h"
#include "guild_service_query_context.h"
#include "guild_service_welfare_context.h"
#include "guild_service_auth_context.h"

#include "protobuf/guildservicebasic.service.pb.h"
#include "protobuf/guildservicequery.service.pb.h"
#include "protobuf/guildservicewelfare.service.pb.h"
#include "util/time_util.hh"
#include "rpc_root.h"
#include "guild/guild.h"

FIXTURE_BEGIN(test_guild_service_welfare)

std::array<uint64_t, 10> role_uuid_list;
std::array<uint64_t, 10> guild_id_list;
std::array<uint64_t, 10> guild_red_envelope_uid_list;
std::array<guild_service::token_type, 10> token_list;

bool is_auto_approval = true;

const char* argv[] = {"test_welfare", "--config=test_welfare_box.cfg"};
kratos::service::ServiceBox* box = new kratos::service::ServiceBox();
uint32_t test_round = 0;

SETUP([&]() {
  std::cout << "\n==================================== "
            << "Round " << test_round++
            << " ====================================\n";
  srand(static_cast<unsigned int>(time(nullptr)));

  for (auto& it : role_uuid_list) {
    it = static_cast<uint64_t>(rand() % 5000000 + 1);
  }

  guild_id_list.fill(0ull);
  guild_red_envelope_uid_list.fill(0ull);

  box->start(2, argv);
})

/// 服务开始
#define BOX_SERVICE_START()                                                       \
  auto context_imp_ptr =                                                      \
      kratos::make_unique_pool_ptr<kratos::service::ServiceContextImpl>(box); \
  auto context_ptr =                                                          \
      dynamic_cast<kratos::service::ServiceContext*>(context_imp_ptr.get());  \
  ASSERT_TRUE(guild_service::GuildServiceBasicContext::Init(context_ptr));    \
  ASSERT_TRUE(guild_service::GuildServiceQueryContext::Init(context_ptr));    \
  ASSERT_TRUE(guild_service::GuildServiceWelfareContext::Init(context_ptr));  \
  ASSERT_TRUE(guild_service::GuildServiceAuthContext::Init(context_ptr));

/// 服务等待
#define BOX_SERVICE_WAIT(ms)                                          \
  {                                                               \
    auto start = kratos::util::get_os_time_millionsecond();       \
    while (true) {                                                \
      auto now = kratos::util::get_os_time_millionsecond();       \
      if (now - start > ms) {                                     \
        break;                                                    \
      }                                                           \
      std::this_thread::sleep_for(std::chrono::milliseconds(10)); \
    }                                                             \
  }

/// 服务运行
#define BOX_SERVICE_RUN(ms)                                           \
  {                                                               \
    auto start = kratos::util::get_os_time_millionsecond();       \
    while (true) {                                                \
      guild_service::GuildServiceBasicContext::Tick(              \
          kratos::util::get_os_time_millionsecond());             \
      guild_service::GuildServiceQueryContext::Tick(              \
          kratos::util::get_os_time_millionsecond());             \
      guild_service::GuildServiceWelfareContext::Tick(            \
          kratos::util::get_os_time_millionsecond());             \
      guild_service::GuildServiceAuthContext::Tick(               \
          kratos::util::get_os_time_millionsecond());             \
      auto now = kratos::util::get_os_time_millionsecond();       \
      if (now - start > ms) {                                     \
        break;                                                    \
      }                                                           \
      std::this_thread::sleep_for(std::chrono::milliseconds(10)); \
    }                                                             \
  }

/// 服务停止
#define BOX_SERVICE_STOP(ms)                                          \
  {                                                                   \
    BOX_SERVICE_RUN(ms)                                               \
    ASSERT_TRUE(guild_service::GuildServiceBasicContext::Uninit());   \
    ASSERT_TRUE(guild_service::GuildServiceQueryContext::Uninit());   \
    ASSERT_TRUE(guild_service::GuildServiceWelfareContext::Uninit()); \
    ASSERT_TRUE(guild_service::GuildServiceAuthContext::Uninit());    \
  }

CASE(TestGuildServiceWelfare0) {
  BOX_SERVICE_START()
  co(
    std::cout << '\n'; for (int i = 0; i < 4; ++i) {
    RegisterArg arg;
    arg.account = guild_service::kTestAccountList[i];
    arg.passwd = guild_service::kTestPasswdList[i];
    rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));

    std::cout << "Register"
              << "\t账号:" << arg.account << "\t密码:" << arg.passwd << '\n';

    auto res = std::make_shared<RegisterRes>();
    try {
      guild_service::GuildServiceAuthContext::Register(call, arg, res);
      {
        std::cout << "Register"
                  << "\t结果:" << static_cast<int>(res->result)
                  << "\t凭证:" << res->token
                  << "\t角色唯一id:" << res->role_uuid << '\n';
      }

      ASSERT_TRUE(res->result == guildserviceauth_cpp::ErrorCode::ERR_SUCCESS);
      ASSERT_TRUE(res->token != 0);
      ASSERT_TRUE(res->role_uuid != 0);

      token_list[i] = res->token;
      role_uuid_list[i] = res->role_uuid;
    } catch (std::exception& ex) {
      std::cerr << "Register exception &:" << ex.what() << std::endl;
    }
  }) BOX_SERVICE_STOP(2000)
}

/// 注册账号
CASE(TestGuildServiceWelfare1) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';

      LoginArg arg; arg.token = token_list[0];
      std::cout << "Login"
                << "\t凭证:" << arg.token << '\n';

      auto res = std::make_shared<LoginRes>();
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));
      try {
        guild_service::GuildServiceWelfareContext::Login(call, arg, res);
        {
          std::cout << "Login"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "Login exception &:" << ex.what() << std::endl;
      }
  )
  BOX_SERVICE_STOP(500)
}

/// 创建公会
CASE(TestGuildServiceWelfare2) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';

      CreateGuildArg arg; arg.token = token_list[0];
      arg.name = "guild" + std::to_string(arg.token);
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "CreateGuild"
                << "\t凭证:" << arg.token << "\t公会名字:" << arg.name
                << '\n';

      auto res = std::make_shared<CreateGuildRes>();

      try {
        guild_service::GuildServiceBasicContext::CreateGuild(call, arg, res);
        {
          std::cout << "CreateGuild"
                    << "\t结果:" << static_cast<int>(res->result)
                    << "\t公会id:" << res->id << '\n';
        }
        ASSERT_TRUE(res->result == guildservicebasic_cpp::ErrorCode::ERR_SUCCESS);
        ASSERT_TRUE(res->id != 0);

        guild_id_list[0] = res->id;
      } catch (std::exception & ex) {
        std::cerr << "CreateGuild exception &:" << ex.what() << std::endl;
      }) BOX_SERVICE_STOP(500)
}

/// 加入公会
CASE(TestGuildServiceWelfare3) {
  BOX_SERVICE_START() {
    std::cout << '\n';
    co(
      {
        SetAutoApprovalArg arg;

        arg.token = token_list[0];
        arg.is_auto_approval = is_auto_approval;
        rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
            std::shared_ptr<rpc::StubCallImpl>(nullptr));

        std::cout << "SetAutoApproval"
                  << "\t凭证:" << arg.token
                  << "\t是否自动同意入会:" << (arg.is_auto_approval ? 1 : 0)
                  << '\n';

        auto res = std::make_shared<SetAutoApprovalRes>();
        try {
          guild_service::GuildServiceBasicContext::SetAutoApproval(call, arg, res);
          {
            std::cout << "SetAutoApproval"
                      << "\t结果:" << static_cast<int32_t>(res->result) << '\n';
          }
          ASSERT_TRUE(res->result == guildservicebasic_cpp::ErrorCode::ERR_SUCCESS);
        } catch (std::exception& ex) {
          std::cerr << "SetAutoApproval exception &:" << ex.what() << std::endl;
        }
      }
      BOX_SERVICE_WAIT(500) {
        ApplyJoinGuildArg arg;
        arg.token = token_list[1];
        arg.guild_id = guild_id_list[0];
        arg.invite_role_uuid = role_uuid_list[0];
        rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));

        std::cout << "ApplyJoinGuild"
                  << "\t凭证:" << arg.token << "\t公会id:" << arg.guild_id
                  << "\t发起邀请的角色唯一id:" << arg.invite_role_uuid << '\n';

        auto res = std::make_shared<ApplyJoinGuildRes>();
        try {
          guild_service::GuildServiceBasicContext::ApplyJoinGuild(call, arg, res);
          {
            std::cout << "ApplyJoinGuild"
                      << "\t结果:" << static_cast<int32_t>(res->result) << '\n';
          }
          ASSERT_TRUE(res->result == guildservicebasic_cpp::ErrorCode::ERR_SUCCESS);
        } catch (std::exception& ex) {
          std::cerr << "ApplyJoinGuild exception &:" << ex.what() << std::endl;
        }
      }
    )
    BOX_SERVICE_STOP(1500)
  }
}

/// 发送公会红包
CASE(TestGuildServiceWelfare4) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';

      SendGuildRedEnvelopeArg arg;
      arg.token = token_list[0];
      arg.brief.content = std::string("Red") + std::to_string(arg.token);
      arg.brief.type =
          guildservicewelfare_cpp::RedEnvelopeType::RED_ENVELOPE_TYPE_ORDINARY;
      arg.brief.money = 100;
      arg.brief.count = 2;
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "SendGuildRedEnvelope"
                << "\t凭证:" << arg.token
                << "\t红包名字:" << arg.brief.content
                << "\t红包类型:" << static_cast<int>(arg.brief.type)
                << "\t红包金额:" << arg.brief.money
                << "\t红包数量:" << arg.brief.count
                << '\n';

      auto res = std::make_shared<SendGuildRedEnvelopeRes>();

      try {
        guild_service::GuildServiceWelfareContext::SendGuildRedEnvelope(call, arg, res);
        {
          std::cout << "SendGuildRedEnvelope"
                    << "\t结果:" << static_cast<int>(res->result)
                    << "\t红包uid:" << res->red_envelope_uid << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
        ASSERT_TRUE(res->red_envelope_uid != 0);
        
        guild_red_envelope_uid_list[0] = res->red_envelope_uid;
      } catch (std::exception & ex) {
        std::cerr << "SendGuildRedEnvelope exception &:" << ex.what() << std::endl;
      }) BOX_SERVICE_STOP(500)
}

/// 抢公会红包
CASE(TestGuildServiceWelfare5) {
  BOX_SERVICE_START()
  co(std::cout << '\n';

     for (int i = 0; i < 2; ++i) {
       GrabGuildRedEnvelopeArg arg;
       arg.token = token_list[i];
       arg.red_envelope_uid = guild_red_envelope_uid_list[0];
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



       std::cout << "GrabGuildRedEnvelope"
                 << "\t凭证:" << arg.token
                 << "\t红包uuid:" << arg.red_envelope_uid << '\n';

       auto res = std::make_shared<GrabGuildRedEnvelopeRes>();

       try {
         guild_service::GuildServiceWelfareContext::GrabGuildRedEnvelope(call, arg,
                                                                         res);
         {
           std::cout << "GrabGuildRedEnvelope"
                     << "\t结果:" << static_cast<int>(res->result)
                     << "\t发红包的凭证:" << res->brief.sender_role_uuid
                     << "\t红包总金额:" << res->brief.money << '\n';
           for (const auto& grabber : res->grabber_list) {
             std::cout << "\t"
                       << "\t抢到红包的凭证:" << grabber.role_uuid
                       << "\t红包金额:" << grabber.money
                       << "\t抢红包时间戳:" << grabber.grab_timestamp << '\n';
             ASSERT_TRUE(grabber.role_uuid != 0);
             ASSERT_TRUE(grabber.money != 0);
             ASSERT_TRUE(grabber.grab_timestamp != 0);
           }
         }
         ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
         ASSERT_TRUE(res->brief.sender_role_uuid != 0);
       } catch (std::exception& ex) {
         std::cerr << "GrabGuildRedEnvelope exception &:" << ex.what()
                   << std::endl;
       }
     }) BOX_SERVICE_STOP(500)
}

/// 设置拍卖出价
CASE(TestGuildServiceWelfare6) {
  BOX_SERVICE_START()
  co(std::cout << '\n';

       SetGuildAuctionOfferArg arg; arg.token = token_list[0]; arg.item_uuid = 1;
       arg.offer = 100;
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "SetGuildAuctionOffer"
                << "\t凭证:" << arg.token << "\t道具uuid:" << arg.item_uuid
                << "\t出价:" << arg.offer << '\n';

       auto res = std::make_shared<SetGuildAuctionOfferRes>();

       try {
        guild_service::GuildServiceWelfareContext::SetGuildAuctionOffer(call, arg,
                                                                        res);
        {
          std::cout << "SetGuildAuctionOffer"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "SetGuildAuctionOffer exception &:" << ex.what()
                  << std::endl;
      }
     ) BOX_SERVICE_STOP(500)
}

/// 设置道具关注
CASE(TestGuildServiceWelfare7) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';

      SetGuildAuctionAttentionArg arg; arg.token = token_list[0];
      arg.item_uuid = 1; arg.is_attention = true;
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "SetGuildAuctionAttention"
                << "\t凭证:" << arg.token << "\t道具uuid:" << arg.item_uuid
                << "\t是否关注:" << arg.is_attention << '\n';

      auto res = std::make_shared<SetGuildAuctionAttentionRes>();

      try {
        guild_service::GuildServiceWelfareContext::SetGuildAuctionAttention(call, 
            arg, res);
        {
          std::cout << "SetGuildAuctionAttention"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "SetGuildAuctionAttention exception &:" << ex.what()
                  << std::endl;
      }) BOX_SERVICE_STOP(500)
}


/// 添加仓库道具
CASE(TestGuildServiceWelfare8) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';
      AddGuildRepositoryCellItemArg arg;
      arg.token = token_list[0]; arg.item_id = 1;
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "AddGuildRepositoryCellItem"
                << "\t凭证:" << arg.token << "\t道具id:" << arg.item_id << '\n';

      auto res = std::make_shared<AddGuildRepositoryCellItemRes>();

      try {
        guild_service::GuildServiceWelfareContext::AddGuildRepositoryCellItem(call, 
            arg, res);
        {
          std::cout << "AddGuildRepositoryCellItem"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "AddGuildRepositoryCellItem exception &:" << ex.what()
                  << std::endl;
      }) BOX_SERVICE_STOP(500)
}

/// 添加仓库道具
CASE(TestGuildServiceWelfare9) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';
      GetGuildRepositoryRoleViewArg arg;
      arg.token = token_list[0];
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "GetGuildRepositoryRoleView"
                << "\t凭证:" << arg.token << '\n';

      auto res = std::make_shared<GetGuildRepositoryRoleViewRes>();

      try {
        guild_service::GuildServiceQueryContext::GetGuildRepositoryRoleView(call, 
            arg, res);
        {
          std::cout << "GetGuildRepositoryRoleView"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicequery_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "GetGuildRepositoryRoleView exception &:" << ex.what()
                  << std::endl;
      }) BOX_SERVICE_STOP(500)
}

/// 删除仓库道具
CASE(TestGuildServiceWelfare10) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n';
      DelGuildRepositoryCellItemArg arg;
      arg.token = token_list[0]; arg.item_uuid = 1;
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "DelGuildRepositoryCellItem"
                << "\t凭证:" << arg.token << "\t道具id:" << arg.item_uuid << '\n';

      auto res = std::make_shared<DelGuildRepositoryCellItemRes>();

      try {
        guild_service::GuildServiceWelfareContext::DelGuildRepositoryCellItem(call,
            arg, res);
        {
          std::cout << "DelGuildRepositoryCellItem"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "DelGuildRepositoryCellItem exception &:" << ex.what()
                  << std::endl;
      }) BOX_SERVICE_STOP(500)
}

/// 查询公会福利奖励
CASE(TestGuildServiceWelfare11) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n'; QueryGuildWelfareAwardArg arg; arg.token = token_list[0];
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "QueryGuildWelfareAward"
                << "\t凭证:" << arg.token << '\n';

      auto res = std::make_shared<QueryGuildWelfareAwardRes>();

      try {
        guild_service::GuildServiceQueryContext::QueryGuildWelfareAward(call, arg,
                                                                        res);
        {
          std::cout << "QueryGuildWelfareAward"
                    << "\t结果:" << static_cast<int>(res->result)
                    << "\t奖励:" << res->award << '\n';
        }
        ASSERT_TRUE(res->result == guildservicequery_cpp::ErrorCode::ERR_SUCCESS);
        ASSERT_TRUE(res->award > 0);
      } catch (std::exception& ex) {
        std::cerr << "QueryGuildWelfareAward exception &:" << ex.what()
                  << std::endl;
      }) BOX_SERVICE_STOP(500)

}

/// 获取公会福利奖励
CASE(TestGuildServiceWelfare12) {
  BOX_SERVICE_START()
  co(
      std::cout << '\n'; GetGuildWelfareAwardArg arg; arg.token = token_list[0];
      rpc::StubCallPtr call = std::dynamic_pointer_cast<rpc::StubCall>(
         std::shared_ptr<rpc::StubCallImpl>(nullptr));



      std::cout << "GetGuildWelfareAward"
                << "\t凭证:" << arg.token << '\n';

      auto res = std::make_shared<GetGuildWelfareAwardRes>();

      try {
        guild_service::GuildServiceWelfareContext::GetGuildWelfareAward(call, arg,
                                                                        res);
        {
          std::cout << "GetGuildWelfareAward"
                    << "\t结果:" << static_cast<int>(res->result) << '\n';
        }
        ASSERT_TRUE(res->result == guildservicewelfare_cpp::ErrorCode::ERR_SUCCESS);
      } catch (std::exception& ex) {
        std::cerr << "GetGuildWelfareAward exception &:" << ex.what()
                  << std::endl;
      }) BOX_SERVICE_STOP(500)
}

FIXTURE_END(test_guild_service_welfare)
